home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- * pic_pak.c - "PicPak" - IFF ILBM picture manipulation functions *
- * (c) 1990 Videoworks Computer Applications *
- * All rights reserved. *
- * *
- * Written by Paul T. Miller *
- * *
- * DISCLAIMER: *
- * Feel free to use these routines or derivatives in your own code, but *
- * please leave credit in your documentation. This code is NOT public *
- * domain, and I am only allowing use of it because I'm a nice guy and I *
- * want to show people how to effectively use their code. If you make any *
- * modifications or enhancements to this code, please let me know. *
- * *
- * Send comments/suggestions to: *
- * Paul Miller *
- * The MBT, Coconut Telegraph, The TARDIS *
- * *
- * Program Name: N/A *
- * Version: 1 *
- * Revision: 3 *
- *-------------------------------------------------------------------------*
- * File: (pic_pak.c) IFF package routines *
- *-------------------------------------------------------------------------*
- * Modification History *
- * Date Author Comment *
- * -------- ------ ------- *
- * 10-02-90 PTM Created. Pic allocation/freeing with specified memtype
- * 10-03-90 PTM iff.library hooks
- * 10-08-90 PTM clean up memory allocation
- * 11-28-90 PTM SetImageType(), custom processing of non-standard forms
- * ViewPort fade/color set functions, color-cycling
- * 12-01-90 PTM SHAM Chunk/ColorMap support - improve file parsing
- * 12-02-90 PTM SHAM Copper-list code, ViewPort support code
- * 12-06-90 PTM Add image decompression buffer
- * 12-07-90 PTM Free mask plane if present in a Frame BitMap
- * 10-13-91 PTM re-prototype
- ***************************************************************************/
-
- #ifndef PIC_PAK_H
- #include "pic_pak.h"
- #endif
-
- extern struct Custom far custom;
- extern struct GfxBase *GfxBase;
- extern struct IntuitionBase *IntuitionBase;
- extern struct Library *DOSBase;
-
- /* Some IFF parsing structs/constants */
- #define BUFFER_SIZE 32000 /* image decompression buffer */
-
- #define MAKE_ID(a,b,c,d) (((long)(a)<<24)|((long)(b)<<16)|((long)(c)<<8)|(long)(d))
-
- /* IFF types we may encounter */
- #define FORM MAKE_ID('F', 'O', 'R', 'M')
- #define ILBM MAKE_ID('I', 'L', 'B', 'M')
- #define BMHD MAKE_ID('B', 'M', 'H', 'D')
- #define CMAP MAKE_ID('C', 'M', 'A', 'P')
- #define BODY MAKE_ID('B', 'O', 'D', 'Y')
- #define CAMG MAKE_ID('C', 'A', 'M', 'G')
- #define CRNG MAKE_ID('C', 'R', 'N', 'G')
- #define SHAM MAKE_ID('S', 'H', 'A', 'M')
- #define DYCP MAKE_ID('D', 'Y', 'C', 'P')
- #define CTBL MAKE_ID('C', 'T', 'B', 'L')
- #define GRAB MAKE_ID('G', 'R', 'A', 'B')
- #define SPRT MAKE_ID('S', 'P', 'R', 'T')
- #define CCRT MAKE_ID('C', 'C', 'R', 'T')
- #define DPPV MAKE_ID('D', 'P', 'P', 'V')
- #define DPPS MAKE_ID('D', 'P', 'P', 'S')
-
- #define byte(n) (((n + 15) >> 4) << 1) /* Word aligned width in bytes. */
-
- struct BitMapHeader {
- UWORD w,h; /* Raster width & height. */
- UWORD x,y; /* Pixel position. */
- UBYTE nPlanes; /* Number of source bitplanes. */
- UBYTE masking; /* Masking... good for nothing maybe? */
- UBYTE compression; /* Packed or unpacked? */
- UBYTE pad1; /* We don't like odd length structures. */
- UWORD transparentColor; /* Maybe good for... */
- UBYTE xAspect, yAspect; /* Kind of quotient, width / height. */
- WORD pageWidth, pageHeight; /* Source page size. */
- };
-
- /* IFF Stuff */
- union typekludge {
- char type_str[4];
- long type_long;
- };
- struct ChunkHeader {
- union typekludge chunktype;
- long chunksize;
- };
- #define TYPE chunktype.type_long
- #define STRTYPE chunktype.type_str
-
- /* Masking techniques */
- #define mskNone 0
- #define mskHasMask 1
- #define mskHasTransparentColor 2
- #define mskLasso 3
-
- /* Compression techniques */
- #define cmpNone 0
- #define cmpByteRun1 1
-
- /* color-cycling stuff */
- #define CRNG_NORATE 36 /* Don't cycle this range. */
- #define CRNG_ACTIVE 1 << 0 /* This range is active. */
- #define CRNG_REVERSE 1 << 1 /* This range is cycling backwards. */
-
- /* GraphiCraft private cycling chunk. */
- struct CcrtChunk {
- WORD direction;
- UBYTE start;
- UBYTE end;
- LONG seconds;
- LONG microseconds;
- WORD pad;
- };
-
- /* some color-cycling globals (used only if color-cycling is enabled) */
- struct CycleData *cdata = NULL;
- int i, j; /* general-purpose indexes used by cycler */
-
- UWORD fade_delay = 0;
- ULONG max_bufsize = BUFFER_SIZE;
-
- struct Pic *AllocatePic(UWORD width, UWORD height, UBYTE depth, UBYTE memtype)
- {
- struct Pic *pic;
- struct BitMap *bitmap;
- ULONG i, size, memsize;
-
- if (memtype == NULL)
- memtype = MEMTYPE_CHIP;
-
- pic = (struct Pic *)AllocMem(PIC_SIZE, MEMF_CLEAR);
- if (!pic) return(NULL);
-
- bitmap = &pic->BitMap;
-
- InitBitMap(bitmap, (long)depth, (long)width, (long)height);
-
- pic->Width = width;
- pic->Height = height;
- pic->Depth = depth;
- pic->Colors = 1<<depth;
-
- size = bitmap->BytesPerRow * bitmap->Rows;
- memsize = size * (ULONG)depth;
-
- if (memtype != MEMTYPE_NONE)
- {
- /* attempt to allocate a chunk of the required memory size and type */
- if (memtype == MEMTYPE_ANY) /* if ANY type, try CHIP first */
- {
- bitmap->Planes[0] = (PLANEPTR)AllocMem(memsize, MEMF_CHIP);
- if (!bitmap->Planes[0])
- memtype = MEMTYPE_FAST; /* out of CHIP, try for FAST */
- }
-
- if (memtype == MEMTYPE_CHIP)
- bitmap->Planes[0] = (PLANEPTR)AllocMem(memsize, MEMF_CHIP);
-
- if (memtype == MEMTYPE_FAST)
- bitmap->Planes[0] = (PLANEPTR)AllocMem(memsize, MEMF_FAST);
-
- if (!bitmap->Planes[0]) /* couldn't get the memory */
- {
- FreePic(pic);
- return(NULL);
- }
- for (i = 1; i < depth; i++) /* set the plane pointers */
- bitmap->Planes[i] = (PLANEPTR)(bitmap->Planes[0] + (i * size));
- }
- if (memtype == MEMTYPE_ANY) /* actually got CHIP ram */
- memtype = MEMTYPE_CHIP;
-
- pic->Memtype = memtype;
-
- return(pic);
- }
-
- void FreePic(struct Pic *pic)
- {
- ULONG size, chunksize;
- struct BitMap *bm;
-
- if (pic)
- {
- if (bm = &pic->BitMap)
- {
- size = bm->BytesPerRow * bm->Rows;
- chunksize = size * (ULONG)bm->Depth;
-
- if (bm->Planes[0])
- FreeMem(bm->Planes[0], chunksize);
- }
- if (pic->PicExt)
- {
- switch (pic->Type)
- {
- case PICTYPE_SHAM:
- FreeMem(pic->PicExt, SHAMDATA_SIZE);
- break;
- case PICTYPE_DHIRES:
- size = pic->Height * DHIRES_COLORS * sizeof(WORD);
- FreeMem(pic->PicExt, size);
- break;
- }
- }
- FreeMem(pic, PIC_SIZE);
- }
- }
-
- struct Frame *AllocateFrame(UWORD width, UWORD height, UBYTE depth)
- {
- struct Frame *frame;
- struct BitMap *bitmap;
- ULONG i, size, memsize;
-
- frame = (struct Frame *)AllocMem(FRAME_SIZE, MEMF_CLEAR);
- if (!frame) return(NULL);
-
- bitmap = &frame->BitMap;
-
- InitBitMap(bitmap, (long)depth, (long)width, (long)height);
-
- frame->Width = width;
- frame->Height = height;
-
- size = bitmap->BytesPerRow * bitmap->Rows;
- memsize = size * (ULONG)depth;
-
- bitmap->Planes[0] = (PLANEPTR)AllocMem(memsize, MEMF_CHIP);
- if (!bitmap->Planes[0])
- {
- FreeMem(frame, FRAME_SIZE);
- return(NULL);
- }
- for (i = 1; i < depth; i++) /* set the plane pointers */
- bitmap->Planes[i] = (PLANEPTR)(bitmap->Planes[0] + (i * size));
-
- return(frame);
- }
-
- void FreeFrame(struct Frame *frame)
- {
- ULONG size, chunksize;
- struct BitMap *bm;
-
- if (frame)
- {
- if (bm = &frame->BitMap)
- {
- size = RASSIZE(bm->BytesPerRow * 8, bm->Rows);
- chunksize = size * (ULONG)bm->Depth;
-
- if (bm->Planes[0])
- FreeMem(bm->Planes[0], chunksize);
- if (bm->Planes[bm->Depth]) /* extra mask plane */
- FreeMem(bm->Planes[bm->Depth], size);
- }
- FreeMem(frame, FRAME_SIZE);
- }
- }
-
- struct Pic *LoadPic(STRPTR filename, UBYTE memtype)
- {
- return(LoadImage(filename, NULL, PICTYPE_NORMAL, memtype));
- }
-
- struct Pic *LoadPic2BitMap(STRPTR filename, struct BitMap *bitmap)
- {
- return(LoadImage(filename, bitmap, PICTYPE_NORMAL, MEMTYPE_NONE));
- }
-
- struct Frame *LoadFrame(STRPTR filename)
- {
- return((struct Frame *)LoadImage(filename, NULL, PICTYPE_FRAME, NULL));
- }
-
- struct Pic *LoadImage(STRPTR filename, struct BitMap *bitmap, UBYTE type, UBYTE memtype)
- {
- struct Pic *pic = NULL;
- struct Frame *frame = NULL;
- struct BitMapHeader bmhd;
- struct ChunkHeader ch;
- FILE *file;
- LONG formsize, subtype;
- UWORD version;
- ULONG size;
-
- file = fopen(filename, "r");
- if (!file)
- return(NULL);
-
- if (!fread((char *)&ch, sizeof(struct ChunkHeader), 1, file))
- {
- fclose(file);
- return(NULL);
- }
- if (ch.TYPE != FORM) /* not an IFF file */
- {
- fclose(file);
- return(NULL);
- }
-
- if (!fread((char *)&subtype, sizeof(subtype), 1, file))
- {
- fclose(file);
- return(NULL);
- }
- formsize = ch.chunksize - sizeof(subtype);
- if (subtype != ILBM) /* not an ILBM image */
- {
- fclose(file);
- return(NULL);
- }
-
- while (formsize > 0)
- {
- if (!fread((char *)&ch, sizeof(struct ChunkHeader), 1, file))
- {
- fclose(file);
- if (pic) FreePic(pic);
- if (frame) FreeFrame(frame);
- return(NULL);
- }
- formsize -= sizeof(struct ChunkHeader);
-
- switch (ch.TYPE)
- {
- case BMHD:
- fread((char *)&bmhd, ch.chunksize, 1, file);
-
- /* some error checking */
- if (bmhd.nPlanes < 1 || bmhd.nPlanes > 8)
- {
- fclose(file);
- return(NULL);
- }
- if (bitmap) /* application has supplied a BitMap */
- memtype = MEMTYPE_NONE;
-
- if (type == PICTYPE_FRAME)
- {
- frame = AllocateFrame(bmhd.w, bmhd.h, bmhd.nPlanes);
- if (!frame)
- {
- fclose(file);
- return(NULL);
- }
- frame->X = bmhd.w;
- frame->Y = bmhd.h;
- }
- else
- {
- pic = AllocatePic(bmhd.w, bmhd.h, bmhd.nPlanes, memtype);
- if (!pic)
- {
- fclose(file);
- return(NULL);
- }
- }
- break;
- case CMAP:
- if (type == PICTYPE_FRAME)
- {
- fseek(file, ch.chunksize, 1);
- break;
- }
- pic->Colors = LoadCMAP(file, ch.chunksize, &pic->Colormap[0]);
- break;
- case CAMG:
- if (type == PICTYPE_FRAME)
- {
- fseek(file, ch.chunksize, 1);
- break;
- }
- fread((char *)&subtype, sizeof(subtype), 1, file);
- pic->ViewModes = (ULONG)subtype;
- if ((UWORD)pic->ViewModes == NULL)
- pic->ViewModes >>= 16L;
- pic->ViewModes &= ~(SPRITES|VP_HIDE|PFBA|GENLOCK_AUDIO|GENLOCK_VIDEO);
- break;
- case CRNG:
- case CCRT:
- if (type == PICTYPE_FRAME || pic->Cycles == MAXCRANGES)
- {
- fseek(file, ch.chunksize, 1);
- break;
- }
- LoadCycleRange(file, &pic->CRanges[pic->Cycles], ch.TYPE);
- pic->Cycles++;
- break;
- case SHAM:
- if (type == PICTYPE_FRAME)
- {
- fseek(file, ch.chunksize, 1);
- break;
- }
- pic->PicExt = (APTR)AllocMem(SHAMDATA_SIZE, NULL);
- if (!pic->PicExt)
- fseek(file, ch.chunksize, 1);
- else
- {
- fread((char *)&version, sizeof(UWORD), 1, file);
- ch.chunksize -= sizeof(UWORD);
- if (version == 0)
- {
- fread((char *)pic->PicExt, ch.chunksize, 1, file);
- pic->Type = PICTYPE_SHAM;
- }
- else
- fseek(file, ch.chunksize, 1);
- }
- break;
- case CTBL:
- if (type == PICTYPE_FRAME)
- {
- fseek(file, ch.chunksize, 1);
- break;
- }
- size = pic->Height * DHIRES_COLORS * sizeof(WORD);
- pic->PicExt = (APTR)AllocMem(size, NULL);
- if (!pic->PicExt)
- fseek(file, ch.chunksize, 1);
- else
- {
- fread((char *)pic->PicExt, ch.chunksize, 1, file);
- pic->Type = PICTYPE_DHIRES;
- }
- break;
- case BODY:
- if (type == PICTYPE_FRAME && frame)
- {
- if (!LoadRaster(file, ch.chunksize, &frame->BitMap.Planes[0], &bmhd))
- {
- fclose(file);
- FreeFrame(frame);
- return(NULL);
- }
- }
- if (type != PICTYPE_FRAME)
- {
- if (!bitmap)
- bitmap = &pic->BitMap;
- if (!LoadRaster(file, ch.chunksize, &bitmap->Planes[0], &bmhd))
- {
- fclose(file);
- FreePic(pic);
- return(NULL);
- }
- }
- /* make sure the BODY isn't off a few bytes */
- if (formsize - ch.chunksize > 0)
- ch.chunksize += (formsize - ch.chunksize);
- break;
- default:
- fseek(file, ch.chunksize, 1);
- break;
- }
- formsize -= ch.chunksize;
- if (ch.chunksize & 1) /* odd-length chunk */
- {
- formsize--;
- fseek(file, 1L, 1);
- }
- }
- fclose(file);
-
- if (type == PICTYPE_FRAME)
- return((struct Pic *)frame);
-
- SetImageType(pic); /* perform any post-processing/identification */
-
- /* now double-check the display size flags */
- if (bmhd.pageHeight > 242)
- pic->ViewModes |= LACE;
- if (bmhd.pageWidth >= 640)
- pic->ViewModes |= HIRES;
-
- return(pic);
- }
-
- /* GetPicAttrs()
- - return the specified picture's size, depth, and viewmode information
- in supplied pointer variables
- */
-
- GetPicAttrs(STRPTR filename, WORD *w, WORD *h, WORD *d, ULONG *vm)
- {
- struct Pic *pic;
-
- /* load just the header information */
- pic = LoadImage(filename, NULL, NULL, MEMTYPE_NONE);
- if (pic)
- {
- *w = pic->Width;
- *h = pic->Height;
- *d = pic->Depth;
- *vm = pic->ViewModes;
- FreePic(pic);
- return(1);
- }
- return(NULL);
- }
-
- /* Pic2BitMap()
- - download Pic imagery stored in FAST RAM to the specified BitMap
- */
- Pic2BitMap(struct Pic *pic, struct BitMap *bm)
- {
- ULONG i, size;
-
- if (pic && bm)
- {
- if (pic->Memtype == MEMTYPE_CHIP)
- {
- BltBitMap(&pic->BitMap, 0, 0, bm, 0, 0, pic->Width,pic->Height,
- 0xc0, 0xff, NULL);
- return(1);
- }
-
- if (pic->Depth != bm->Depth)
- return(NULL);
- if (pic->Width != bm->BytesPerRow * 8)
- return(NULL);
- if (pic->Height != bm->Rows)
- return(NULL);
-
- size = pic->BitMap.BytesPerRow * pic->BitMap.Rows;
- for (i = 0; i < bm->Depth; i++)
- memcpy(bm->Planes[i], pic->BitMap.Planes[i], size);
-
- return(1);
- }
- return(NULL);
- }
-
- BOOL LoadRaster(FILE *file, ULONG chunksize, PLANEPTR *BitPlanes, struct BitMapHeader *BMHeader)
- {
- register LONG i, j, k;
- register BYTE ChkVal;
- register UBYTE Value, SoFar;
- UBYTE Compr, Depth;
- LONG Height, Width;
- PLANEPTR Planes[9]; /* 9 for possible bitmask. */
- UBYTE *memory = NULL;
-
- for(i = 0; i < 9; i++)
- Planes[i] = NULL;
-
- Width = byte(BMHeader->w);
- Height = BMHeader->h;
- Depth = BMHeader->nPlanes;
- Compr = BMHeader->compression;
-
- if (Compr > cmpByteRun1 || !BitPlanes)
- return(FALSE);
-
- for(i = 0; i < Depth; i++)
- Planes[i] = BitPlanes[i];
-
- if (BMHeader->masking == mskHasMask)
- Depth++;
-
- if (Compr == cmpNone)
- {
- for (k = 0; k < Height; k++)
- {
- for (j = 0; j < Depth; j++)
- {
- if (Planes[j])
- {
- fread((char *)Planes[j], Width, 1, file);
- Planes[j] += Width;
- }
- else
- fseek(file, Width, 1);
- }
- }
- }
- if (Compr == cmpByteRun1)
- {
- if (chunksize < max_bufsize)
- {
- memory = (UBYTE *)AllocMem(chunksize, NULL);
- if (memory)
- {
- fread(memory, chunksize, 1, file);
- mem_decompress(memory, &Planes[0], Width, Height, Depth);
- FreeMem(memory, chunksize);
- return(1);
- }
- }
- for (k = 0; k < Height; k++)
- {
- for (j = 0; j < Depth; j++)
- {
- for (SoFar = 0; SoFar < Width ;)
- {
- ChkVal = fgetc(file);
-
- if (ChkVal > 0)
- {
- if (Planes[j])
- {
- fread(Planes[j], ChkVal + 1, 1, file);
- Planes[j] += ChkVal + 1;
- }
- else
- fseek(file, ChkVal + 1, 1);
-
- SoFar += ChkVal + 1;
- }
- else
- {
- if (ChkVal != 128)
- {
- Value = fgetc(file);
-
- for (i = 0; i <= -ChkVal; i++)
- {
- if (Planes[j])
- {
- *Planes[j] = Value;
- Planes[j]++;
- }
- SoFar++;
- }
- }
- }
- }
- }
- }
- }
- return(TRUE);
- }
-
- void mem_decompress(register UBYTE *ptr, PLANEPTR *Planes, LONG Width, LONG Height, UBYTE Depth)
- {
- LONG i, j, k;
- register BYTE ChkVal;
- UBYTE Value, SoFar;
-
- for (k = 0; k < Height; k++)
- {
- for (j = 0; j < Depth; j++)
- {
- for (SoFar = 0; SoFar < Width ;)
- {
- ChkVal = *ptr;
- ptr++;
-
- if (ChkVal > 0)
- {
- if (Planes[j])
- {
- memcpy(Planes[j], ptr, ChkVal+1);
- Planes[j] += ChkVal + 1;
- ptr += ChkVal + 1;
- }
- else
- ptr += ChkVal + 1;
-
- SoFar += ChkVal + 1;
- }
- else
- {
- if (ChkVal != 128)
- {
- Value = *ptr;
- ptr++;
-
- for (i = 0; i <= -ChkVal; i++)
- {
- if (Planes[j])
- {
- *Planes[j] = Value;
- Planes[j]++;
- }
- SoFar++;
- }
- }
- }
- }
- }
- }
- }
-
- void SetPicReadBufSize(ULONG size)
- {
- max_bufsize = size;
- }
-
- UWORD LoadCMAP(FILE *file, LONG csize, UWORD *cmap)
- {
- UBYTE *ctable;
- UWORD i, n;
- LONG len;
-
- len = csize;
- if (len > (MAXCOLORS * 3))
- len = MAXCOLORS * 3;
-
- ctable = (UBYTE *)AllocMem(csize, NULL);
- if (!ctable)
- return(NULL);
-
- fread((char *)ctable, csize, 1, file);
-
- for (i = n = 0; n < len; i++, n += 3)
- cmap[i] = ((ctable[n]>>4)<<8)+((ctable[n+1]>>4)<<4)+(ctable[n+2]>>4);
-
- FreeMem(ctable, csize);
-
- return(i);
- }
-
- void LoadCycleRange(FILE *file, CRange *range, LONG type)
- {
- struct CcrtChunk crtchunk;
-
- switch (type)
- {
- case CRNG:
- fread((char *)range, sizeof(CRange), 1, file);
-
- /* Carefully determine the activity of the chunk. */
- if (range->active == CRNG_NORATE || !range->rate || range->low == range->high)
- range->active = 0;
-
- /* Recalculate speed value. */
- if (range->rate > 0)
- range->rate = 16384 / range->rate;
- else
- range->rate = 0;
- break;
- case CCRT:
- fread((char *)&crtchunk, sizeof(struct CcrtChunk), 1, file);
-
- /* We have located a CCRT chunk, now make it a CRNG chunk. */
- range->low = crtchunk.start;
- range->high = crtchunk.end;
-
- if (crtchunk.direction != 0)
- range->active = CRNG_ACTIVE;
- else
- range->active = 0;
-
- if (crtchunk.direction > 0)
- range->active |= CRNG_REVERSE;
-
- /* Recalculate speed (by Carolyn Scheppner). */
- range->rate = 16384 / (crtchunk.seconds * 60 +
- (crtchunk.microseconds + 8334) / 16667);
- if (!range->rate || range->low == range->high)
- range->active = 0;
- if (range->rate > 0)
- range->rate = 16384 / range->rate;
- else
- range->rate = 0;
- break;
- }
- }
-
- void SetImageType(struct Pic *pic)
- {
- /* handle custom processing of non-standard picture types */
- if (pic->Type) /* already set */
- {
- switch (pic->Type)
- {
- case PICTYPE_SHAM:
- pic->Colors = 16;
- pic->ViewModes |= HAM;
- break;
- }
- return;
- }
-
- if (pic->ViewModes & HAM)
- {
- pic->Colors = 16;
- pic->Type = PICTYPE_HAM;
- return;
- }
- if (pic->Width <= 320 && pic->Height <= 200 && pic->Depth == 6)
- {
- pic->Colors = MAXCOLORS;
- pic->ViewModes = EXTRA_HALFBRITE;
- pic->Type = PICTYPE_EHB;
- return;
- }
- pic->Type = PICTYPE_NORMAL;
- }
-
- /**********************************************************/
- /* GENERAL-PURPOSE PICTURE/VIEWPORT MANIPULATION ROUTINES */
- /**********************************************************/
-
- /*****************/
- /* COLOR-CYCLING */
- /*****************/
-
- struct CycleData {
- struct ViewPort *vp;
- struct Pic *pic;
- struct Interrupt *vblank;
- UBYTE cycling;
- UBYTE pad;
- UWORD temp_col;
- UWORD cmap[MAXCOLORS];
- WORD ticks[16];
- };
-
- typedef void (*FPTR)();
-
- InitCycler()
- {
- cdata = (struct CycleData *)AllocMem(sizeof(struct CycleData), MEMF_CLEAR);
- if (!cdata)
- return(NULL);
-
- cdata->vblank = (struct Interrupt *)AllocMem(sizeof(struct Interrupt), MEMF_CLEAR);
- if (!cdata->vblank)
- return(NULL);
-
- cdata->vblank->is_Data = NULL;
- cdata->vblank->is_Code = (FPTR)cycle;
- cdata->vblank->is_Node.ln_Succ = NULL;
- cdata->vblank->is_Node.ln_Pred = NULL;
- cdata->vblank->is_Node.ln_Type = NT_INTERRUPT;
- cdata->vblank->is_Node.ln_Pri = 0;
- cdata->vblank->is_Node.ln_Name = "PicPak_Color_Cycler";
-
- AddIntServer(INTB_VERTB, cdata->vblank);
-
- return(1);
- }
-
- void FreeCycler()
- {
- if (cdata)
- {
- if (cdata->vblank)
- {
- StopCycling();
-
- RemIntServer(INTB_VERTB, cdata->vblank);
- FreeMem(cdata->vblank, sizeof(struct Interrupt));
- WaitTOF();
- WaitTOF();
- WaitTOF();
- }
- FreeMem(cdata, sizeof(struct CycleData));
- }
- }
-
- __saveds void cycle()
- {
- if (cdata->cycling)
- {
- for (i = 0; i < cdata->pic->Cycles; i++)
- {
- /* Increment event counter. */
- cdata->ticks[i]++;
-
- /* Is this one up to cycle next? */
- if (cdata->ticks[i] == cdata->pic->CRanges[i].rate)
- {
- /* Reset event counter for this range. */
-
- cdata->ticks[i] = 0;
-
- /* Is this range active? */
-
- if (!(cdata->pic->CRanges[i].active & CRNG_ACTIVE))
- continue;
-
- /* Cycling backwards? */
- if(cdata->pic->CRanges[i].active & CRNG_REVERSE)
- {
- /* Move the colours. */
- cdata->temp_col = cdata->cmap[cdata->pic->CRanges[i].low];
-
- for(j = cdata->pic->CRanges[i].low; j < cdata->pic->CRanges[i].high; j++)
- cdata->cmap[j] = cdata->cmap[j+1];
-
- cdata->cmap[cdata->pic->CRanges[i].high] = cdata->temp_col;
- }
- else
- {
- /* This one is cycling forwards. */
-
- cdata->temp_col = cdata->cmap[cdata->pic->CRanges[i].high];
-
- for(j = cdata->pic->CRanges[i].high; j > cdata->pic->CRanges[i].low; j--)
- cdata->cmap[j] = cdata->cmap[j-1];
-
- cdata->cmap[cdata->pic->CRanges[i].low] = cdata->temp_col;
- }
- /* Okay, everything has been moved, now load the new palette. */
- LoadRGB4(cdata->vp, cdata->cmap, cdata->pic->Colors);
- }
- }
- }
- }
-
- void StartCycling(struct ViewPort *vp, struct Pic *pic)
- {
- if (cdata && pic->Cycles)
- {
- cdata->pic = pic;
- cdata->vp = vp;
-
- /* reset the palette and event counters */
- for (i = 0; i < pic->Colors; i++)
- cdata->cmap[i] = pic->Colormap[i];
-
- for (i = 0; i < pic->Cycles; i++)
- cdata->ticks[i] = 0;
-
- cdata->cycling = 1;
- }
- }
-
- void StopCycling()
- {
- /* restore old colormap */
- if (cdata)
- {
- if (cdata->cycling)
- LoadRGB4(cdata->vp, &cdata->pic->Colormap[0], cdata->pic->Colors);
-
- cdata->cycling = NULL;
- }
- }
-
- void ToggleCycling()
- {
- if (cdata)
- {
- if (cdata->cycling)
- StopCycling();
- else
- StartCycling(cdata->vp, cdata->pic);
- }
- }
-
- IsCycling()
- {
- if (!cdata) return(NULL);
- return((int)cdata->cycling);
- }
-
- /***************************/
- /* VIEWPORT-COLOR ROUTINES */
- /***************************/
-
- void SetViewPortPicColors(struct ViewPort *vp, struct Pic *pic)
- {
- switch (pic->Type)
- {
- case PICTYPE_SHAM:
- InitSHAM(vp, pic);
- break;
- case PICTYPE_DHIRES:
- InitDHIRES(vp, pic);
- break;
- default:
- LoadRGB4(vp, &pic->Colormap[0], pic->Colors);
- }
- }
-
- void ClearViewPortColors(struct ViewPort *vp, UWORD colors)
- {
- register int i;
-
- if (colors > MAXCOLORS)
- colors = MAXCOLORS;
-
- for (i = 0; i < colors; i++)
- SetRGB4(vp, i, 0, 0, 0);
- }
-
- #define RED(c) ((c >> 8) & 0xF)
- #define GREEN(c) ((c >> 4) & 0xF)
- #define BLUE(c) (c & 0xF)
-
- void FadeViewPortIn(struct ViewPort *vp, UWORD *cm, UWORD colors)
- {
- ULONG rf[MAXCOLORS], gf[MAXCOLORS], bf[MAXCOLORS];
- register USHORT rgb, r, g, b;
- WORD i, n;
-
- if (colors > MAXCOLORS)
- colors = MAXCOLORS;
-
- for (i = 0; i < colors; i++)
- {
- rgb = cm[i];
- rf[i] = (RED(rgb) << 16) / 15;
- gf[i] = (GREEN(rgb) << 16) / 15;
- bf[i] = (BLUE(rgb) << 16) / 15;
- }
- for (n = 1; n < 16; n++)
- {
- for (i = 0; i < colors; i++)
- {
- r = (((rf[i] * n) + 0x8000) >> 16);
- g = (((gf[i] * n) + 0x8000) >> 16);
- b = (((bf[i] * n) + 0x8000) >> 16);
-
- SetRGB4(vp, i, r, g, b);
- }
- if (fade_delay > 0) Delay(fade_delay);
- }
- }
-
- void FadeViewPortOut(struct ViewPort *vp, UWORD colors)
- {
- ULONG rf[MAXCOLORS], gf[MAXCOLORS], bf[MAXCOLORS];
- register UWORD rgb, r, g, b;
- WORD i, n;
- UWORD start = 0;
-
- if (GetRGB4(vp->ColorMap, 0) == 0x0000)
- start = 1;
-
- if (colors > MAXCOLORS)
- colors = MAXCOLORS;
-
- for (i = start; i < colors; i++)
- {
- rgb = GetRGB4(vp->ColorMap, i);
- rf[i] = (RED(rgb) << 16) / 15;
- gf[i] = (GREEN(rgb) << 16) / 15;
- bf[i] = (BLUE(rgb) << 16) / 15;
- }
- for (n = 14; n >= 0; n--)
- {
- for (i = start; i < colors; i++)
- {
- r = (((rf[i] * n) + 0x8000) >> 16);
- g = (((gf[i] * n) + 0x8000) >> 16);
- b = (((bf[i] * n) + 0x8000) >> 16);
-
- SetRGB4(vp, i, r, g, b);
- }
- if (fade_delay > 0) Delay(fade_delay);
- }
- }
-
- void SetFadeSpeed(UWORD val)
- {
- fade_delay = val;
- }
-
- /* SPECIAL IMAGE TYPE INITIALIZATION CODE */
-
- /* SHAM Copper-list initialization */
- InitSHAM(struct ViewPort *vp, struct Pic *pic)
- {
- register UWORD i, n;
- register struct SHAMData *sham;
- struct UCopList *ucoplist = NULL;
- BOOL lace = 0;
- register WORD view_dx = IntuitionBase->ViewLord.DxOffset;
-
- sham = (struct SHAMData *)pic->PicExt;
- if (!sham) return(NULL);
-
- SetRGB4(vp, 0, 0, 0, 0);
- for (i = 1; i < 16; i++)
- SetRGB4(vp, i, (UBYTE)(sham->ColorTable[0][i] / (UWORD)256),
- (UBYTE)(sham->ColorTable[0][i] / (UWORD)16 % 16),
- (UBYTE)(sham->ColorTable[0][i] % 16));
-
- ucoplist = (struct UCopList *)AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR);
- if (!ucoplist) return(NULL);
-
- if (pic->Height > LORES_HEIGHT)
- lace = 1;
-
- CINIT(ucoplist, (199*16));
- for (i = 1; i < 200; i++)
- {
- if (lace)
- {
- if (view_dx < 114)
- {
- CWAIT(ucoplist, i + i - 2, 0);
- }
- else
- {
- if (view_dx < 129)
- {
- CWAIT(ucoplist, i + i - 2, 0);
- }
- else
- {
- CWAIT(ucoplist, i + i, 0);
- }
- }
- }
- else
- {
- if (view_dx < 128)
- {
- CWAIT(ucoplist, i - 1, 0);
- }
- else
- {
- CWAIT(ucoplist, i, 0);
- }
- }
- for (n = 1; n < 16; n++)
- CMOVE(ucoplist, custom.color[n], (WORD)sham->ColorTable[i][n]);
- }
- CEND(ucoplist);
-
- Forbid();
- vp->UCopIns = ucoplist;
- Permit();
- RethinkDisplay();
-
- return(1);
- }
-
- /* Dynamic-HIRES Copper-list initialization */
- InitDHIRES(struct ViewPort *vp, struct Pic *pic)
- {
- register UWORD i, n;
- UWORD *ctbl;
- struct UCopList *ucoplist = NULL;
- BOOL lace = 0;
-
- ctbl = (UWORD *)pic->PicExt;
- if (!ctbl) return(NULL);
-
- ucoplist = (struct UCopList *)AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR);
- if (!ucoplist) return(NULL);
-
- if (pic->Height > LORES_HEIGHT)
- lace = 1;
-
- CINIT(ucoplist, (pic->Height * 16));
- for (i = 0; i < pic->Height; i++)
- {
- CWAIT(ucoplist, i, 0);
- for (n = 0; n < 16; n++)
- CMOVE(ucoplist, custom.color[n], (WORD)*(ctbl+(i*16)+n));
- }
- CEND(ucoplist);
-
- Forbid();
- vp->UCopIns = ucoplist;
- Permit();
- RethinkDisplay();
-
- return(1);
- }
-
- void FreeSHAM(struct ViewPort *vp)
- {
- if (vp->UCopIns)
- FreeVPortCopLists(vp);
- }
-